package com.pai4j.user.service.group;

import com.pai4j.common.enums.*;
import com.pai4j.common.exception.BusinessException;
import com.pai4j.common.util.JsonUtil;
import com.pai4j.domain.vo.request.group.*;
import com.pai4j.domain.vo.response.group.GroupMemberResponseVO;
import com.pai4j.domain.vo.response.group.JoinGroupResponseVO;
import com.pai4j.domain.vo.response.UserBaseResponseInfoVO;
import com.pai4j.user.repository.dao.*;
import com.pai4j.user.repository.entity.*;
import com.pai4j.user.service.UserService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.core.util.Assert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 群成员管理服务
 */
@Slf4j
@Service
public class GroupMemberService {

    @Resource
    private IGroupMemberDAO groupMemberDAO;
    
    @Resource
    private IGroupInfoDAO groupInfoDAO;
    
    @Resource
    private IGroupOperationLogDAO groupOperationLogDAO;
    
    @Resource
    private IGroupInvitationDAO groupInvitationDAO;
    
    @Autowired
    private UserService userService;
    
    @Autowired
    private GroupMemberCacheService groupMemberCacheService;
    
    @Autowired
    private GroupService groupService;
    
    // 使用@Lazy注解打破与GroupJoinApplicationService的循环依赖
    @Autowired
    @org.springframework.context.annotation.Lazy
    private GroupJoinApplicationService groupJoinApplicationService;
    
    // 注入ApplicationContext，用于动态获取User2GroupAccountRelationService
    // 这样可以避免与User2GroupAccountRelationService的循环依赖
    @Autowired
    private ApplicationContext applicationContext;
    
    // 懒加载账号关系服务
    private com.pai4j.user.service.relation.User2GroupAccountRelationService user2GroupAccountRelationService;
    
    /**
     * 获取账号关系服务实例（懒加载）
     */
    private com.pai4j.user.service.relation.User2GroupAccountRelationService getAccountRelationService() {
        if (user2GroupAccountRelationService == null) {
            user2GroupAccountRelationService = applicationContext.getBean(
                com.pai4j.user.service.relation.User2GroupAccountRelationService.class);
        }
        return user2GroupAccountRelationService;
    }

    /**
     * 加入群聊
     * 统一处理：群成员表 + 账号关系表 + 缓存同步
     * 
     * @return JoinGroupResponseVO 加群结果
     *         status=1: 成功加入
     *         status=2: 已提交审批申请
     *         status=3: 群已满
     *         status=4: 已在群内
     *         status=5: 群禁止加入
     */
    @Transactional
    public JoinGroupResponseVO joinGroup(JoinGroupRequestVO request) {
        // 1. 验证群聊是否存在
        GroupInfoEntity groupInfo = groupInfoDAO.findByPaiId(request.getGroupPaiId());
        if (groupInfo == null) {
            throw new BusinessException("群聊不存在");
        }
        
        log.info("用户 {} 尝试加入群聊 {}，加入方式：{}", request.getUserAccount(), request.getGroupPaiId(), request.getJoinType());
        
        // 2. 检查群聊状态
        if (!groupInfo.getStatus().equals(1)) {
            throw new BusinessException("群聊已停用");
        }
        
        // 3. 检查用户是否已在群内
        if (groupMemberDAO.existsByGroupPaiIdAndUserAccount(request.getGroupPaiId(), request.getUserAccount())) {
            log.warn("用户 {} 已在群 {} 内", request.getUserAccount(), request.getGroupPaiId());
            return JoinGroupResponseVO.failed(request.getGroupPaiId(), request.getUserAccount(), 4, "您已在该群内");
        }
        
        // 4. 检查群成员数量限制
        Long memberCount = groupMemberDAO.countActiveMembers(request.getGroupPaiId());
        if (memberCount >= groupInfo.getMaxMembers()) {
            log.warn("群 {} 成员已达上限，当前：{}，上限：{}", request.getGroupPaiId(), memberCount, groupInfo.getMaxMembers());
            return JoinGroupResponseVO.failed(request.getGroupPaiId(), request.getUserAccount(), 3, "群成员已达上限");
        }
        
        // 5. 根据群加入方式验证权限
        // 注意：如果是审批通过(joinType=6)，则跳过此检查
        if (request.getJoinType() == null || !request.getJoinType().equals(GroupJoinTypeEnum.APPROVED.getType())) {
            // 5.1 禁止加入
            if (groupInfo.getJoinMode().equals(2)) {
                log.warn("群 {} 禁止加入", request.getGroupPaiId());
                return JoinGroupResponseVO.failed(request.getGroupPaiId(), request.getUserAccount(), 5, "该群禁止加入");
            }
            
            // 5.2 需要审批：自动创建审批申请
            if (groupInfo.getJoinMode().equals(1)) {
                log.info("群 {} 需要审批，为用户 {} 自动创建加群申请", request.getGroupPaiId(), request.getUserAccount());
                
                // 检查是否已有待处理的申请
                if (groupJoinApplicationService.hasUserPendingApplication(request.getGroupPaiId(), request.getUserAccount())) {
                    log.warn("用户 {} 在群 {} 已有待处理的申请", request.getUserAccount(), request.getGroupPaiId());
                    return JoinGroupResponseVO.failed(request.getGroupPaiId(), request.getUserAccount(), 2, "您已提交过申请，请等待审批");
                }
                
                // 创建审批申请
                ApplyJoinGroupRequestVO applyRequest = new ApplyJoinGroupRequestVO();
                applyRequest.setGroupPaiId(request.getGroupPaiId());
                applyRequest.setApplicantAccount(request.getUserAccount());
                applyRequest.setApplicationMessage(request.getApplyMessage());
                
                Long applicationId = groupJoinApplicationService.applyJoinGroup(applyRequest);
                
                log.info("用户 {} 的加群申请已创建，申请ID：{}，等待群 {} 的管理员审批", 
                        request.getUserAccount(), applicationId, request.getGroupPaiId());
                
                return JoinGroupResponseVO.pending(request.getGroupPaiId(), request.getUserAccount(), applicationId);
            }
        }
        
        // 6. 创建群成员记录
        Date now = new Date();
        GroupMemberEntity member = new GroupMemberEntity();
        member.setGroupPaiId(request.getGroupPaiId());
        member.setUserAccount(request.getUserAccount());
        member.setMemberRole(GroupMemberRoleEnum.MEMBER.getRole());
        member.setJoinType(request.getJoinType());
        member.setJoinTime(now);
        member.setInviterAccount(request.getInviterAccount());
        member.setMemberStatus(GroupMemberStatusEnum.NORMAL.getStatus());
        member.setCreateDate(now);
        member.setUpdateDate(now);
        
        groupMemberDAO.save(member);
        
        // 7. 记录操作日志
        recordOperationLog(request.getGroupPaiId(), request.getUserAccount(), null, 
                          GroupOperationTypeEnum.JOIN_GROUP.getType(), 
                          "用户加入群聊", null);
        
        // 8. 同步账号关系表和缓存（用户订阅群组）
        // 强一致性要求：账号关系同步失败则整个事务回滚
        getAccountRelationService().subscribe(request.getUserAccount(), request.getGroupPaiId());
        log.info("用户 {} 账号关系同步成功：群 {}", request.getUserAccount(), request.getGroupPaiId());
        
        // 9. 刷新群成员相关缓存
        groupMemberCacheService.addUserToGroupCache(request.getGroupPaiId(), request.getUserAccount());
        groupMemberCacheService.clearUserGroupCache(request.getUserAccount());
        
        log.info("用户 {} 成功加入群聊 {}，所有数据已同步（群成员表+账号关系表+缓存）", request.getUserAccount(), request.getGroupPaiId());
        return JoinGroupResponseVO.success(request.getGroupPaiId(), request.getUserAccount());
    }

    /**
     * 退出群聊
     * 统一处理：群成员表 + 账号关系表 + 缓存同步
     */
    @Transactional
    public boolean leaveGroup(LeaveGroupRequestVO request) {
        // 1. 验证群成员是否存在
        GroupMemberEntity member = groupMemberDAO.findByGroupPaiIdAndUserAccount(
                request.getGroupPaiId(), request.getUserAccount());
        if (member == null) {
            throw new BusinessException("用户不在群内");
        }
        
        // 2. 检查是否为群主
        if (GroupMemberRoleEnum.isOwner(member.getMemberRole())) {
            Assert.isEmpty("群主不能直接退群,请先转让群主或解散群聊");
            throw new BusinessException("群主不能直接退群，请先转让群主或解散群聊");
        }
        
        // 3. 更新成员状态为主动退群
        Date now = new Date();
        member.setMemberStatus(GroupMemberStatusEnum.LEFT.getStatus());
        member.setUpdateDate(now);
        groupMemberDAO.save(member);
        
        // 4. 记录操作日志
        recordOperationLog(request.getGroupPaiId(), request.getUserAccount(), null, 
                          GroupOperationTypeEnum.LEAVE_GROUP.getType(), 
                          "用户退出群聊" + (StringUtils.isNotBlank(request.getReason()) ? "，原因：" + request.getReason() : ""), 
                          null);
        
        // 5. 同步账号关系表（用户取消订阅群组）
        // 强一致性要求：账号关系取消失败则整个事务回滚
        getAccountRelationService().unsubscribe(request.getUserAccount(), request.getGroupPaiId());
        log.info("用户 {} 账号关系取消成功：群 {}", request.getUserAccount(), request.getGroupPaiId());
        
        // 6. 刷新群成员相关缓存
        groupMemberCacheService.removeUserFromGroupCache(request.getGroupPaiId(), request.getUserAccount());
        groupMemberCacheService.clearUserGroupCache(request.getUserAccount());
        
        log.info("用户 {} 退出群聊 {}，所有数据已同步（群成员表+账号关系表+缓存）", request.getUserAccount(), request.getGroupPaiId());
        return true;
    }

    /**
     * 踢出群成员
     * 统一处理：群成员表 + 账号关系表 + 缓存同步
     */
    @Transactional
    public boolean kickMembers(KickMemberRequestVO request) {
        // 1. 验证操作人权限
        GroupMemberEntity operator = groupMemberDAO.findByGroupPaiIdAndUserAccount(
                request.getGroupPaiId(), request.getOperatorAccount());
        if (operator == null || !GroupMemberRoleEnum.hasAdminPermission(operator.getMemberRole())) {
            throw new BusinessException("无权限执行此操作");
        }
        
        // 2. 批量踢出成员
        Date now = new Date();
        List<String> kickedMembers = new ArrayList<>();
        
        for (String targetAccount : request.getTargetAccounts()) {
            GroupMemberEntity targetMember = groupMemberDAO.findByGroupPaiIdAndUserAccount(
                    request.getGroupPaiId(), targetAccount);
            
            if (targetMember == null) {
                log.warn("用户 {} 不在群 {} 内，跳过踢出操作", targetAccount, request.getGroupPaiId());
                continue;
            }
            
            // 不能踢出群主，管理员不能踢出其他管理员（除非是群主操作）
            if (GroupMemberRoleEnum.isOwner(targetMember.getMemberRole())) {
                log.warn("不能踢出群主 {}", targetAccount);
                continue;
            }
            
            if (GroupMemberRoleEnum.isAdmin(targetMember.getMemberRole()) && 
                !GroupMemberRoleEnum.isOwner(operator.getMemberRole())) {
                log.warn("管理员不能踢出其他管理员 {}", targetAccount);
                continue;
            }
            
            // 更新成员状态为被踢出
            targetMember.setMemberStatus(GroupMemberStatusEnum.KICKED.getStatus());
            targetMember.setUpdateDate(now);
            groupMemberDAO.save(targetMember);
            
            kickedMembers.add(targetAccount);
            
            // 记录操作日志
            recordOperationLog(request.getGroupPaiId(), request.getOperatorAccount(), targetAccount,
                              GroupOperationTypeEnum.KICK_MEMBER.getType(),
                              "踢出群成员" + (StringUtils.isNotBlank(request.getReason()) ? "，原因：" + request.getReason() : ""),
                              null);
            
            // 同步账号关系表（被踢出的用户取消订阅群组）
            // 强一致性要求：账号关系取消失败则整个事务回滚
            getAccountRelationService().unsubscribe(targetAccount, request.getGroupPaiId());
            log.info("用户 {} 被踢出群 {}，账号关系已同步", targetAccount, request.getGroupPaiId());
            
            // 刷新缓存
            groupMemberCacheService.removeUserFromGroupCache(request.getGroupPaiId(), targetAccount);
            groupMemberCacheService.clearUserGroupCache(targetAccount);
        }
        
        // 批量踢出后，刷新群成员列表缓存
        if (!kickedMembers.isEmpty()) {
            groupMemberCacheService.refreshGroupMemberCache(request.getGroupPaiId());
        }
        
        log.info("操作人 {} 踢出群 {} 成员：{}，所有数据已同步（群成员表+账号关系表+缓存）", request.getOperatorAccount(), request.getGroupPaiId(), kickedMembers);
        return !kickedMembers.isEmpty();
    }

    /**
     * 管理群成员（任命/撤销管理员、禁言/解禁、转让群主）
     */
    @Transactional
    public boolean manageGroupMember(ManageGroupMemberRequestVO request) {
        // 1. 验证操作人权限
        GroupMemberEntity operator = groupMemberDAO.findByGroupPaiIdAndUserAccount(
                request.getGroupPaiId(), request.getOperatorAccount());
        if (operator == null) {
            throw new BusinessException("操作人不在群内");
        }
        
        // 2. 验证被操作人是否在群内
        GroupMemberEntity targetMember = groupMemberDAO.findByGroupPaiIdAndUserAccount(
                request.getGroupPaiId(), request.getTargetAccount());
        if (targetMember == null) {
            throw new BusinessException("被操作用户不在群内");
        }
        
        Date now = new Date();
        String operationDesc = "";
        
        // 3. 根据操作类型执行相应操作
        switch (GroupOperationTypeEnum.getByType(request.getOperationType())) {
            // 任命管理员
            case APPOINT_ADMIN:
                if (!GroupMemberRoleEnum.isOwner(operator.getMemberRole())) {
                    throw new BusinessException("只有群主可以任命管理员");
                }
                if (GroupMemberRoleEnum.isOwner(targetMember.getMemberRole())) {
                    throw new BusinessException("不能对群主执行此操作");
                }
                
                targetMember.setMemberRole(GroupMemberRoleEnum.ADMIN.getRole());
                operationDesc = "任命为管理员";
                break;
            // 撤销管理员
            case REMOVE_ADMIN:
                if (!GroupMemberRoleEnum.isOwner(operator.getMemberRole())) {
                    throw new BusinessException("只有群主可以撤销管理员");
                }
                if (!GroupMemberRoleEnum.isAdmin(targetMember.getMemberRole())) {
                    throw new BusinessException("该用户不是管理员");
                }
                
                targetMember.setMemberRole(GroupMemberRoleEnum.MEMBER.getRole());
                operationDesc = "撤销管理员";
                break;
            // 禁言成员
            case MUTE_MEMBER:
                if (!GroupMemberRoleEnum.hasAdminPermission(operator.getMemberRole())) {
                    throw new BusinessException("无权限执行此操作");
                }
                if (GroupMemberRoleEnum.isOwner(targetMember.getMemberRole())) {
                    throw new BusinessException("不能对群主执行此操作");
                }
                if (GroupMemberRoleEnum.isAdmin(targetMember.getMemberRole()) && 
                    !GroupMemberRoleEnum.isOwner(operator.getMemberRole())) {
                    throw new BusinessException("管理员不能禁言其他管理员");
                }
                
                targetMember.setMemberStatus(GroupMemberStatusEnum.MUTED.getStatus());
                targetMember.setMuteUntil(request.getMuteUntil());
                operationDesc = "禁言成员至 " + (request.getMuteUntil() != null ? request.getMuteUntil() : "永久");
                break;
            // 解除禁言
            case UNMUTE_MEMBER:
                if (!GroupMemberRoleEnum.hasAdminPermission(operator.getMemberRole())) {
                    throw new BusinessException("无权限执行此操作");
                }
                
                targetMember.setMemberStatus(GroupMemberStatusEnum.NORMAL.getStatus());
                targetMember.setMuteUntil(null);
                operationDesc = "解除禁言";
                break;
            // 转让群主
            case TRANSFER_OWNER:
                if (!GroupMemberRoleEnum.isOwner(operator.getMemberRole())) {
                    throw new BusinessException("只有群主可以转让群主");
                }
                if (operator.getUserAccount().equals(targetMember.getUserAccount())) {
                    throw new BusinessException("不能转让给自己");
                }
                
                // 原群主变为普通成员
                operator.setMemberRole(GroupMemberRoleEnum.MEMBER.getRole());
                operator.setUpdateDate(now);
                groupMemberDAO.save(operator);
                
                // 新群主
                targetMember.setMemberRole(GroupMemberRoleEnum.OWNER.getRole());
                
                // 更新群信息中的群主ID
                GroupInfoEntity groupInfo = groupInfoDAO.findByPaiId(request.getGroupPaiId());
                if (groupInfo != null) {
                    groupInfo.setOwnerId(request.getTargetAccount());
                    groupInfo.setUpdateDate(now);
                    groupInfoDAO.save(groupInfo);
                }
                
                operationDesc = "转让群主给 " + request.getTargetAccount();
                break;
                
            default:
                throw new BusinessException("不支持的操作类型");
        }
        
        // 4. 保存更新
        targetMember.setUpdateDate(now);
        groupMemberDAO.save(targetMember);
        
        // 5. 记录操作日志
        recordOperationLog(request.getGroupPaiId(), request.getOperatorAccount(), request.getTargetAccount(),
                          request.getOperationType(), operationDesc + 
                          (StringUtils.isNotBlank(request.getReason()) ? "，原因：" + request.getReason() : ""),
                          null);
        
        log.info("操作人 {} 对群 {} 成员 {} 执行操作：{}", 
                request.getOperatorAccount(), request.getGroupPaiId(), request.getTargetAccount(), operationDesc);
        return true;
    }

    /**
     * 获取群成员列表
     */
    public List<GroupMemberResponseVO> getGroupMembers(String groupPaiId) {
        // 1. 先尝试从缓存获取
        List<GroupMemberResponseVO> cachedMembers = groupMemberCacheService.getCachedGroupMembers(groupPaiId);
        if (cachedMembers != null) {
            log.debug("从缓存获取群 {} 成员列表，共 {} 个成员", groupPaiId, cachedMembers.size());
            return cachedMembers;
        }
        
        // 2. 缓存未命中，从数据库查询
        List<GroupMemberEntity> members = groupMemberDAO.findActiveMembers(groupPaiId);
        if (members.isEmpty()) {
            return new ArrayList<>();
        }
        
        // 批量获取用户信息
        List<String> userAccounts = members.stream()
                .map(GroupMemberEntity::getUserAccount)
                .collect(Collectors.toList());
        List<UserBaseResponseInfoVO> userInfos = userService.batchGetUserListInfoFromCache(userAccounts);
        Map<String, UserBaseResponseInfoVO> userInfoMap = userInfos.stream()
                .collect(Collectors.toMap(UserBaseResponseInfoVO::getUserId, u -> u));
        
        // 3. 转换为响应VO
        List<GroupMemberResponseVO> result = members.stream().map(member -> {
            UserBaseResponseInfoVO userInfo = userInfoMap.get(member.getUserAccount());
            return GroupMemberResponseVO.builder()
                    .groupPaiId(member.getGroupPaiId())
                    .userAccount(member.getUserAccount())
                    .userName(userInfo != null ? userInfo.getUserName() : member.getUserAccount())
                    .userAvatar(userInfo != null ? userInfo.getPhoto() : null)
                    .memberRole(member.getMemberRole())
                    .memberRoleName(getRoleName(member.getMemberRole()))
                    .joinType(member.getJoinType())
                    .joinTypeName(getJoinTypeName(member.getJoinType()))
                    .joinTime(member.getJoinTime())
                    .inviterAccount(member.getInviterAccount())
                    .memberStatus(member.getMemberStatus())
                    .memberStatusName(getStatusName(member.getMemberStatus()))
                    .muteUntil(member.getMuteUntil())
                    .nicknameInGroup(member.getNicknameInGroup())
                    .remark(member.getRemark())
                    .ext(json2map(member.getExt()))
                    .createDate(member.getCreateDate())
                    .updateDate(member.getUpdateDate())
                    .build();
        }).collect(Collectors.toList());
        
        // 4. 缓存结果
        groupMemberCacheService.cacheGroupMembers(groupPaiId, result);
        
        return result;
    }

    /**
     * 获取群聊当前人数
     * 仅统计状态正常的成员（排除已退出、被踢出等状态）
     * 
     * @param groupPaiId 群组ID
     * @return 当前群聊人数
     */
    public Long getGroupMemberCount(String groupPaiId) {
        Long count = groupMemberDAO.countActiveMembers(groupPaiId);
        log.debug("群 {} 当前成员数：{}", groupPaiId, count);
        return count;
    }

    /**
     * 获取用户加入的群聊列表
     */
    public List<GroupMemberResponseVO> getUserGroups(String userAccount) {
        List<GroupMemberEntity> members = groupMemberDAO.findUserGroups(userAccount);
        if (members.isEmpty()) {
            return new ArrayList<>();
        }
        
        // 批量获取群信息
        List<String> groupPaiIds = members.stream()
                .map(GroupMemberEntity::getGroupPaiId)
                .collect(Collectors.toList());
        List<GroupInfoEntity> groupInfos = groupInfoDAO.findAllById(
                groupPaiIds.stream().map(paiId -> groupInfoDAO.findByPaiId(paiId).getId()).collect(Collectors.toList()));
        Map<String, GroupInfoEntity> groupInfoMap = groupInfos.stream()
                .collect(Collectors.toMap(GroupInfoEntity::getPaiId, g -> g));
        
        return members.stream().map(member -> {
            GroupInfoEntity groupInfo = groupInfoMap.get(member.getGroupPaiId());
            return GroupMemberResponseVO.builder()
                    .groupPaiId(member.getGroupPaiId())
                    .userAccount(member.getUserAccount())
                    .userName(groupInfo != null ? groupInfo.getName() : member.getGroupPaiId())
                    .userAvatar(groupInfo != null ? groupInfo.getAvatar() : null)
                    .memberRole(member.getMemberRole())
                    .memberRoleName(getRoleName(member.getMemberRole()))
                    .joinType(member.getJoinType())
                    .joinTypeName(getJoinTypeName(member.getJoinType()))
                    .joinTime(member.getJoinTime())
                    .inviterAccount(member.getInviterAccount())
                    .memberStatus(member.getMemberStatus())
                    .memberStatusName(getStatusName(member.getMemberStatus()))
                    .muteUntil(member.getMuteUntil())
                    .nicknameInGroup(member.getNicknameInGroup())
                    .remark(member.getRemark())
                    .ext(json2map(member.getExt()))
                    .createDate(member.getCreateDate())
                    .updateDate(member.getUpdateDate())
                    .build();
        }).collect(Collectors.toList());
    }
    

    /**
     * 记录操作日志
     */
    private void recordOperationLog(String groupPaiId, String operatorAccount, String targetAccount,
                                   Integer operationType, String operationDesc, Map<String, Object> ext) {
        GroupOperationLogEntity log = new GroupOperationLogEntity();
        log.setGroupPaiId(groupPaiId);
        log.setOperatorAccount(operatorAccount);
        log.setTargetAccount(targetAccount);
        log.setOperationType(operationType);
        log.setOperationDesc(operationDesc);
        log.setExt(map2json(ext));
        log.setCreateDate(new Date());
        
        groupOperationLogDAO.save(log);
    }

    /**
     * 获取角色名称
     */
    private String getRoleName(Integer role) {
        GroupMemberRoleEnum roleEnum = GroupMemberRoleEnum.getByRole(role);
        return roleEnum != null ? roleEnum.getRoleName() : "未知";
    }

    /**
     * 获取加入方式名称
     */
    private String getJoinTypeName(Integer joinType) {
        GroupJoinTypeEnum typeEnum = GroupJoinTypeEnum.getByType(joinType);
        return typeEnum != null ? typeEnum.getTypeName() : "未知";
    }

    /**
     * 获取状态名称
     */
    private String getStatusName(Integer status) {
        GroupMemberStatusEnum statusEnum = GroupMemberStatusEnum.getByStatus(status);
        return statusEnum != null ? statusEnum.getStatusName() : "未知";
    }

    /**
     * 将 Map 转换为 JSON 字符串
     */
    private String map2json(Map<String, Object> map) {
        return map == null ? null : JsonUtil.toJsonString(map);
    }




    /**
     * 创建群聊信息记录到专门的群聊表
     * 在账号关系模块创建群聊后，在专门的群聊模块添加群聊信息
     * @data 2025-09-22
     */
    @Transactional
    public boolean createGroupInfoRecord(String groupPaiId, String groupName, String groupPhoto, String ownerAccount) {
        try {
            // 1. 检查群聊信息是否已存在
            GroupInfoEntity existingGroup = groupInfoDAO.findByPaiId(groupPaiId);
            if (existingGroup != null) {
                log.warn("群聊信息记录已存在，跳过创建：groupPaiId={}", groupPaiId);
                return true;
            }
            
            Date now = new Date();
            
            // 2. 创建群聊信息记录
            GroupInfoEntity groupInfo = new GroupInfoEntity();
            groupInfo.setPaiId(groupPaiId);
            groupInfo.setName(groupName);
            groupInfo.setAvatar(groupPhoto);
            groupInfo.setOwnerId(ownerAccount);
            groupInfo.setJoinMode(0); // 默认自由加入
            groupInfo.setMaxMembers(500); // 默认最大500人
            groupInfo.setStatus(1); // 默认启用状态
            groupInfo.setCreateDate(now);
            groupInfo.setUpdateDate(now);
            
            groupInfoDAO.save(groupInfo);
            
            log.info("成功创建群聊信息记录：groupPaiId={}, groupName={}, ownerAccount={}", 
                    groupPaiId, groupName, ownerAccount);
            return true;
            
        } catch (Exception e) {
            log.error("创建群聊信息记录失败：groupPaiId={}, ownerAccount={}", groupPaiId, ownerAccount, e);
            return false;
        }
    }

    /**
     * 创建群聊时设置群主
     * 专门用于群聊创建流程，将创建者设置为群主并记录到群成员表
     */
    @Transactional
    public boolean setGroupOwnerOnCreation(String groupPaiId, String ownerAccount) {
        try {
            // 1. 检查群聊是否存在
            GroupInfoEntity groupInfo = groupInfoDAO.findByPaiId(groupPaiId);
            if (groupInfo == null) {
                log.error("群聊不存在，无法设置群主：groupPaiId={}", groupPaiId);
                return false;
            }
            
            // 2. 检查是否已有群主记录
            GroupMemberEntity existingOwner = groupMemberDAO.findByGroupPaiIdAndUserAccount(groupPaiId, ownerAccount);
            if (existingOwner != null) {
                log.warn("群成员记录已存在，跳过创建：groupPaiId={}, userAccount={}", groupPaiId, ownerAccount);
                return true;
            }
            
            Date now = new Date();
            
            // 3. 创建群主记录
            GroupMemberEntity ownerMember = new GroupMemberEntity();
            ownerMember.setGroupPaiId(groupPaiId);
            ownerMember.setUserAccount(ownerAccount);
            ownerMember.setMemberRole(GroupMemberRoleEnum.OWNER.getRole());
            ownerMember.setJoinType(GroupJoinTypeEnum.CREATE_GROUP.getType());
            ownerMember.setJoinTime(now);
            // 创建者没有邀请人
            ownerMember.setInviterAccount(null);
            ownerMember.setMemberStatus(GroupMemberStatusEnum.NORMAL.getStatus());
            ownerMember.setCreateDate(now);
            ownerMember.setUpdateDate(now);
            
            groupMemberDAO.save(ownerMember);
            
            // 4. 更新群信息表中的群主ID
            groupInfo.setOwnerId(ownerAccount);
            groupInfo.setUpdateDate(now);
            groupInfoDAO.save(groupInfo);
            
            // 5. 记录操作日志
            recordOperationLog(groupPaiId, ownerAccount, null, 
                              GroupOperationTypeEnum.CREATE_GROUP.getType(), 
                              "创建群聊并设置为群主", null);
            
            // 6. 缓存群主信息
            groupMemberCacheService.cacheGroupOwner(groupPaiId, ownerAccount);
            
            log.info("成功设置群主：groupPaiId={}, ownerAccount={}", groupPaiId, ownerAccount);
            return true;
            
        } catch (Exception e) {
            log.error("设置群主失败：groupPaiId={}, ownerAccount={}", groupPaiId, ownerAccount, e);
            return false;
        }
    }

    /**
     * 批量添加群成员（用于群聊创建时）
     * 专门用于群聊创建流程，批量添加初始成员
     * 注意：此方法仅处理群成员表数据，账号关系由createChatGroup中的subscribe统一处理
     */
    @Transactional
    public boolean batchAddMembersOnCreation(String groupPaiId, List<String> memberAccounts, String inviterAccount) {
        try {
            Date now = new Date();
            List<GroupMemberEntity> membersToAdd = new ArrayList<>();
            List<String> addedAccounts = new ArrayList<>();
            
            for (String memberAccount : memberAccounts) {
                // 跳过群主（群主已经在setGroupOwnerOnCreation中添加）
                if (memberAccount.equals(inviterAccount)) {
                    continue;
                }
                
                // 检查是否已存在
                if (groupMemberDAO.existsByGroupPaiIdAndUserAccount(groupPaiId, memberAccount)) {
                    log.warn("群成员已存在，跳过添加：groupPaiId={}, userAccount={}", groupPaiId, memberAccount);
                    continue;
                }
                
                GroupMemberEntity member = new GroupMemberEntity();
                member.setGroupPaiId(groupPaiId);
                member.setUserAccount(memberAccount);
                member.setMemberRole(GroupMemberRoleEnum.MEMBER.getRole());
                member.setJoinType(GroupJoinTypeEnum.INVITED.getType());
                member.setJoinTime(now);
                member.setInviterAccount(inviterAccount);
                member.setMemberStatus(GroupMemberStatusEnum.NORMAL.getStatus());
                member.setCreateDate(now);
                member.setUpdateDate(now);
                
                membersToAdd.add(member);
                addedAccounts.add(memberAccount);
            }
            
            // 批量保存
            if (!membersToAdd.isEmpty()) {
                groupMemberDAO.saveAll(membersToAdd);
                
                // 批量记录操作日志
                for (GroupMemberEntity member : membersToAdd) {
                    recordOperationLog(groupPaiId, inviterAccount, member.getUserAccount(),
                                      GroupOperationTypeEnum.JOIN_GROUP.getType(),
                                      "创建群聊时被邀请加入", null);
                }
                
                log.info("批量添加群成员成功：groupPaiId={}, 添加成员数={}", groupPaiId, membersToAdd.size());
            }
            
            // 刷新群成员缓存
            if (!addedAccounts.isEmpty()) {
                // 批量添加到缓存
                for (String account : addedAccounts) {
                    groupMemberCacheService.addUserToGroupCache(groupPaiId, account);
                }
                // 刷新群成员列表缓存
                groupMemberCacheService.refreshGroupMemberCache(groupPaiId);
                log.info("群 {} 成员缓存已刷新，新增 {} 个成员", groupPaiId, addedAccounts.size());
            }
            
            return true;
            
        } catch (Exception e) {
            log.error("批量添加群成员失败：groupPaiId={}, memberAccounts={}", groupPaiId, memberAccounts, e);
            return false;
        }
    }

    /**
     * 将 JSON 字符串解析为 Map 对象
     */
    @SuppressWarnings("unchecked")
    private Map<String, Object> json2map(String json) {
        return StringUtils.isBlank(json) ? null : JsonUtil.fromJson(json, Map.class);
    }
    
    /**
     * 检查用户是否有指定权限
     * @param groupPaiId 群ID
     * @param userAccount 用户账号
     * @param permission 权限类型：owner-群主，admin-管理员(包括群主)，member-普通成员
     * @return true-有权限，false-无权限
     */
    public boolean hasPermission(String groupPaiId, String userAccount, String permission) {
        GroupMemberEntity member = groupMemberDAO.findByGroupPaiIdAndUserAccount(groupPaiId, userAccount);
        if (member == null) {
            return false;
        }
        
        // 检查成员状态
        if (!GroupMemberStatusEnum.isNormal(member.getMemberStatus())) {
            return false;
        }
        
        switch (permission.toLowerCase()) {
            case "owner":
                // 群主权限
                return GroupMemberRoleEnum.isOwner(member.getMemberRole());
            case "admin":
                // 管理员权限（包括群主）
                return GroupMemberRoleEnum.hasAdminPermission(member.getMemberRole());
            case "member":
                // 普通成员权限（在群内即可）
                return true;
            default:
                return false;
        }
    }
}
